<?php

namespace Helper;

/**
 * 工具类 timed 时间处理
 */
class Timed
{
	private static $needAbs = true;
	private static $forceAbs = false;

	/**
	 * @return string
	 */
	public static function getTimeCode(): string
	{
		return mb_substr($_COOKIE['timezoneCode'], -6);
	}

	public static function getTimezoneName(): string
	{
		return $_COOKIE['timezoneName'] ?? 'Asia/Shanghai';
	}

    /**
     * 获取上1小时整点时间戳
     *
     * @param int $timed
     * @return number
     */
    public static function getHourPreTimed($timed = null)
    {
        if ($timed) {
            return strtotime('-1 hour', strtotime(date('Y-m-d H:00:00', $timed)));
        } else {
            return strtotime('-1 hour', strtotime(date('Y-m-d H:00:00')));
        }
    }

    /**
     * 获取当前小时整点时间戳
     *
     * @return number
     */
    public static function getHourCurrentTimed($timed = null)
    {
        if ($timed) {
            return strtotime(date('Y-m-d H:00:00', $timed));
        } else {
            return strtotime(date('Y-m-d H:00:00'));
        }
    }

    /**
     * 获取下1小时整点时间戳
     *
     * @param int $timed
     * @return number
     */
    public static function getHourNextTimed($timed = null)
    {
        if ($timed) {
            return strtotime('+1 hour', strtotime(date('Y-m-d H:00:00', $timed)));
        } else {
            return strtotime('+1 hour', strtotime(date('Y-m-d H:00:00')));
        }
    }

    /**
     * 获取今天0点时间戳
     *
     * @return number
     */
    public static function getTodayTimed()
    {
        return strtotime(date('Y-m-d'));
    }

    /**
     * 获取昨天0点时间戳
     *
     * @return number
     */
    public static function getYesterdayTimed()
    {
        return strtotime(date('Y-m-d')) - 86400;
    }

    /**
     * 获取上1天0点时间戳
     *
     * @param int $timed
     * @return number
     */
    public static function getDayPreTimed($timed = null)
    {
        if ($timed) {
            return strtotime('-1 day', strtotime(date('Y-m-d', $timed)));
        } else {
            return strtotime('-1 day', strtotime(date('Y-m-d')));
        }
    }

    /**
     * 获取当天0点时间戳
     *
     * @return number
     */
    public static function getDayCurrentTimed($timed = null)
    {
        if ($timed) {
            return strtotime(date('Y-m-d', $timed));
        } else {
            return strtotime(date('Y-m-d'));
        }
    }

    /**
     * 获取下1天0点时间戳
     *
     * @param int $timed
     * @return number
     */
    public static function getDayNextTimed($timed = null)
    {
        if ($timed) {
            return strtotime('+1 day', strtotime(date('Y-m-d', $timed)));
        } else {
            return strtotime('+1 day', strtotime(date('Y-m-d')));
        }
    }

    /**
     * 计算传入时区和中国时区的时差
     * @param $time_zone
     * @return int
     */
    public static function getTimeZoneOffset($time_zone, $time_zone_basic = 'Asia/Shanghai'){

		// 时区动态修改
	    $time_zone = self::dynamicsTimeZone($time_zone);
        $timezone1 = new \DateTimeZone($time_zone_basic);
        $timezone2 = new \DateTimeZone($time_zone);
        $offset1 = $timezone1->getOffset(new \DateTime()); // 系统时区
        $offset2 = $timezone2->getOffset(new \DateTime()); // 商家时区

        return $offset2 - $offset1;
    }

	/**
	 * 将固定时区转为用户动态时区选择
	 * @param $time_zone
	 * @author renfeng
	 * @return mixed
	 */
	public static function dynamicsTimeZone($time_zone)
	{
		if (isset($_GET['dynamics_time_zone']) && $_GET['dynamics_time_zone']) {
			// 校验时区合法性, 去数据库查询
			$time_zone = $_GET['dynamics_time_zone'];
		}
		return $time_zone;
	}

    /**
     * 获得时区
     * @param $time_zone
     * @return int
     */
    public static function getTimeZone($time_zone, $type='hour'){
        $timezone = new \DateTimeZone('America/Sao_Paulo');
        $offset = $timezone->getOffset(new \DateTime());

        $hours = floor($offset / 3600);
        $minutes = abs(floor(($offset % 3600) / 60));

        return "{$hours}:{$minutes}";
    }

    public static function getDayNextTimedTimeZone($timed = null)
    {
        if ($timed) {
            return strtotime('+1 day', $timed);
        } else {
            return strtotime('+1 day', strtotime(date('Y-m-d')));
        }
    }

    /**
     * 获取上周一0点时间戳
     *
     * @param int $timed
     * @return number
     */
    public static function getWeekPreTimed($timed = null)
    {
        if ($timed) {
            return strtotime('-1 week', strtotime(date('o-\\WW', $timed)));
        } else {
            return strtotime('-1 week', strtotime(date('o-\\WW')));
        }
    }

    /**
     * 获取当周一0点时间戳
     *
     * @param int $timed
     * @return number
     */
    public static function getWeekCurrentTimed($timed = null)
    {
        if ($timed) {
            return strtotime(date('o-\\WW', $timed));
        } else {
            return strtotime(date('o-\\WW'));
        }
    }

    /**
     * 获取下周一0点时间戳
     *
     * @param int $timed
     * @return number
     */
    public static function getWeekNextTimed($timed = null)
    {
        if ($timed) {
            return strtotime('+1 week', strtotime(date('o-\\WW', $timed)));
        } else {
            return strtotime('+1 week', strtotime(date('o-\\WW')));
        }
    }

    /**
     * 获取上月1日0点时间戳
     *
     * @param int $timed
     * @return number
     */
    public static function getMonthPreTimed($timed = null)
    {
        if ($timed) {
            return strtotime('-1 month', strtotime(date('Y-m-01', $timed)));
        } else {
            return strtotime('-1 month', strtotime(date('Y-m-01')));
        }
    }

    /**
     * 获取当月1日0点时间戳
     *
     * @param int $timed
     * @return number
     */
    public static function getMonthCurrentTimed($timed = null)
    {
        if ($timed) {
            return strtotime(date('Y-m-01', $timed));
        } else {
            return strtotime(date('Y-m-01'));
        }
    }

    public static function toSql($query){
        $bindings = $query->getBindings();
        $bindings = array_map(function($a){
            return '\''.$a.'\'';
        },$bindings );
        $sql = str_replace('?', '%s', $query->toSql());
        $sql = sprintf($sql, ...$bindings);
        dd($sql);
    }

    /**
     * 获取下月1日0点时间戳
     *
     * @param int $timed
     * @return number
     */
    public static function getMonthNextTimed($timed = null)
    {
        if ($timed) {
            return strtotime('+1 month', strtotime(date('Y-m-01', $timed)));
        } else {
            return strtotime('+1 month', strtotime(date('Y-m-01')));
        }
    }

    public static function getMonthNextTimedTimeZone($timed = null, $offset = 0)
    {
        if ($timed) {
            return strtotime('+1 month', strtotime(date('Y-m-01', $timed)) - $offset);
        } else {
            return strtotime('+1 month', strtotime(date('Y-m-01')) - $offset);
        }
    }

    /**
     * 获取月天数
     *
     * @param int $timed
     * @return number
     */
    public static function getMonthDays($timed)
    {
        return date('t', $timed);
    }

    /**
     * 获取上年1月1日0点时间戳
     *
     * @param int $timed
     * @return number
     */
    public static function getYearPreTimed($timed = null)
    {
        if ($timed) {
            return strtotime('-1 year', strtotime(date('Y-01-01', $timed)));
        } else {
            return strtotime('-1 year', strtotime(date('Y-01-01')));
        }
    }

    /**
     * 获取当年1月1日0点时间戳
     *
     * @param int $timed
     * @return number
     */
    public static function getYearCurrentTimed($timed = null)
    {
        if ($timed) {
            return strtotime(date('Y-01-01', $timed));
        } else {
            return strtotime(date('Y-01-01'));
        }
    }

    /**
     * 获取下年1月1日0点时间戳
     *
     * @param int $timed
     * @return number
     */
    public static function getYearNextTimed($timed = null)
    {
        if ($timed) {
            return strtotime('+1 year', strtotime(date('Y-01-01', $timed)));
        } else {
            return strtotime('+1 year', strtotime(date('Y-01-01')));
        }
    }

    /**
     * 获取当年第一周星期一0点时间戳
     *
     * @param int $timed
     * @return number
     */
    public static function getYearFirstWeekTimed($timed = null)
    {
        if ($timed) {
            return strtotime('first mon of january', $timed);
        } else {
            return strtotime('first mon of january');
        }
    }

	/**
	 * 获取数组参数
	 *
	 * @param \Illuminate\Http\Request $request
	 * @param string $key
	 * @return array
	 */
	public static function getParamArray($request, $key)
	{
		$value = $request->input($key);

		$values = is_array($value) ? $value : json_decode($value, true);

		return is_array($values) ? $values : [];
	}

	/**
	 * 时间格式化
	 * @param $request
	 * @param string $key
	 * @return array
	 */
	public static function datetimeFormat($request, $key = 'datetime', $start_time='', $end_time='', $type = 'day', $add = true){

		$datetime = self::getParamArray($request, $key);
		$start_time = empty($start_time) ? ($datetime[0] ?? strtotime('-1 year')) : $start_time;
		$end_time = empty($end_time) ? ($datetime[1] ?? time()) : $end_time;

		// 1.获取本地时区时间搓
		date_default_timezone_set(self::getJsLocalTimezoneNameByCookie());
		switch ($type){
			case 'hour':
				$start_time_local = strtotime(date('Y-m-d H:00:00', $start_time));
				$end_time_local = strtotime(date('Y-m-d H:59:59', $end_time));
				break;
			case 'day':
				$start_time_local = strtotime(date('Y-m-d 00:00:00', $start_time));
				$end_time_local = strtotime(date('Y-m-d 23:59:59', $end_time));
				break;
			default:
				$start_time_local = $start_time;
				$end_time_local   = $end_time;
				break;
		}

		// 2.获取下拉选择时间戳
		// 2.获取下拉选择时间戳
		$addTime = self::localSubSelectTimezoneSeconds();
		if ($add) {
			$start_time = $start_time_local + $addTime;
			$end_time = $end_time_local + $addTime;
		} else {
			$start_time = $start_time_local;
			$end_time = $end_time_local;
		}

		return [
			$start_time,
			$end_time,
		];
	}

	public static function datetimeFormat1($request, $key = 'datetime', $start_time='', $end_time='', $type = 'day'){

		$datetime = self::getParamArray($request, $key);
		date_default_timezone_set(self::getJsLocalTimezoneNameByCookie());

		$start_time = empty($start_time) ? ($datetime[0] ?? strtotime('-1 year')) : $start_time;
		$end_time = empty($end_time) ? ($datetime[1] ?? time()) : $end_time;

		// 1.获取本地时区时间搓
		switch ($type){
			case 'hour':
				$start_time_local = date('Y-m-d H:00:00', $start_time);
				$end_time_local = date('Y-m-d H:59:59', $end_time);
				break;
			case 'day':
				$start_time_local = date('Y-m-d 00:00:00', $start_time);
				$end_time_local = date('Y-m-d 23:59:59', $end_time);
				break;
			case 's':
				$start_time_local = date('Y-m-d H:i:s', $start_time);
				$end_time_local = date('Y-m-d H:i:s', $end_time);
				break;
			default:
				$start_time_local = date('Y-m-d H:i:s', $start_time);
				$end_time_local = date('Y-m-d H:i:s', $end_time);
				break;
		}

		$start_time = new \DateTime($start_time_local, new \DateTimeZone(self::getTimezoneName()));
		$end_time = new \DateTime($end_time_local, new \DateTimeZone(self::getTimezoneName()));

		return [
			$start_time->getTimestamp(),
			$end_time->getTimestamp(),
		];


		$start_time_local = strtotime($start_time_local);
		$end_time_local = strtotime($end_time_local);


		// 2.获取下拉选择时间戳
		switch ($request->user()->config->local_timezone){
			case 'Etc/GMT+11':
				$localOffset = -11 * 60 * 60;
				break;
			default:
				$localOffset = $request->user()->config->localTimezoneArr->offset;
				break;
		}

		if($request->user()->config->timezoneArr->offset < 0){
			$start_time = $start_time_local +$localOffset - $request->user()->config->timezoneArr->offset;
			$end_time = $end_time_local + $localOffset - $request->user()->config->timezoneArr->offset;
		}elseif($request->user()->config->timezoneArr->offset > 0 && $request->user()->config->timezoneArr->offset < $localOffset){
			$start_time = $start_time_local + ($localOffset - $request->user()->config->timezoneArr->offset);
			$end_time = $end_time_local + ($localOffset - $request->user()->config->timezoneArr->offset);
		}else{
			$start_time = $start_time_local - ($request->user()->config->timezoneArr->offset - $localOffset);
			$end_time = $end_time_local - ($request->user()->config->timezoneArr->offset - $localOffset);
//            dd($tmp->getTimestamp(), $start_time);
		}

		return [
			$start_time,
			$end_time,
		];
	}

	/**
	 * 获取获取本地时间CODE -11:00
	 * @return string
	 */
	public static function getJsLocalTimezoneCodeByCookie(): string
	{
		return mb_substr($_COOKIE['jsLocalTimezoneCode'], -6);
	}

	/**
	 * cookie中获取本地时间name 如Asia/Shanghai
	 * @return string
	 */
	public static function getJsLocalTimezoneNameByCookie(): string
	{
		return $_COOKIE['jsLocalTimezoneName'];
	}

	/**
	 * 本地时区减去选择时区 得到秒
	 * @return int
	 */
	public static function localSubSelectTimezoneSeconds(): int
	{

		$localTime = self::getSecondsByTimeCode(self::getJsLocalTimezoneCodeByCookie());
		$selectTime = self::getSecondsByTimeCode(self::getTimeCode());
		self::localTimeLtZero();
		if ($localTime < $selectTime && self::getNeedAbs() ) {
			return abs(bcsub("$localTime", "$selectTime", 0));
		}
		return bcsub("$localTime", "$selectTime", 0);

	}


	/**
	 * 时间code
	 * @param $code
	 * @return int
	 */
	public static function getSecondsByTimeCode($code): int
	{
		$arr = [
			'-11:00' =>  -39600,
			'-10:00' =>  -36000,
			'-09:30' =>  -34200,
			'-09:00' =>  -32400,
			'-08:00' =>  -28800,
			'-07:00' =>  -25200,
			'-06:00' =>  -21600,
			'-05:00' =>  -18000,
			'-04:00' =>  -14400,
			'-03:00' =>  -10800,
			'-02:30' =>  -9000,
			'-02:00' =>  -7200,
			'-01:00' =>  -3600,
			'00:00' =>  0,
			'+01:00' =>  3600,
			'+02:00' =>  7200,
			'+03:00' =>  10800,
			'+03:30' =>  12600,
			'+04:00' =>  14400,
			'+04:30' =>  16200,
			'+05:00' =>  18000,
			'+05:45' =>  20700,
			'+06:00' =>  21600,
			'+06:30' =>  23400,
			'+07:00' =>  25200,
			'+08:00' =>  28800,
			'+08:45' =>  31500,
			'+09:00' =>  32400,
			'+09:30' =>  34200,
			'+10:00' =>  36000,
			'+10:30' =>  37800,
			'+11:00' =>  39600,
			'+12:00' =>  43200,
			'+13:00' =>  46800,
			'+14:00' =>  50400,
		];

		return $arr[$code] ?? 0;
	}

	private static function getNeedAbs()
	{
		return self::$needAbs;
	}
	public static function setNeedAbs($bool = true)
	{
		return self::$needAbs = $bool;
	}

	public static function localTimeLtZero()
	{
		$localTime = self::getSecondsByTimeCode(self::getJsLocalTimezoneCodeByCookie());
		$selectTime = self::getSecondsByTimeCode(self::getTimeCode());
		if (($localTime < 0 && $selectTime < 0) &&  $localTime < $selectTime) {
			self::setNeedAbs(false);
		}
		if (self::getForceAbs()) {
			self::setNeedAbs(true);
		}
	}

	private static function getForceAbs()
	{
		return self::$forceAbs;
	}

	public static function setForceAbs($bool = true)
	{
		return self::$forceAbs = $bool;
	}

	public static function setForceNotAbs($bool = false)
	{
		return self::$needAbs = $bool;
	}
}
